//SPDX-FileCopyrightText: Copyright 2022-2024 深圳市同心圆网络有限公司
//SPDX-License-Identifier: GPL-3.0-only

package org_api_serv

import (
	"context"
	"fmt"
	"time"

	"atomgit.com/openlinksaas/api-server/api_common"
	"atomgit.com/openlinksaas/api-server/bg_runner/tasks"
	"atomgit.com/openlinksaas/api-server/dao"
	"atomgit.com/openlinksaas/api-server/dao/org_dao"
	"atomgit.com/openlinksaas/api-server/dao/org_eval_dao"
	"atomgit.com/openlinksaas/api-server/dao/user_dao"
	"atomgit.com/openlinksaas/proto-gen-go.git/notices/notices_org"
	"atomgit.com/openlinksaas/proto-gen-go.git/org_api"
	"github.com/google/uuid"
	"go.mongodb.org/mongo-driver/mongo"
)

func (apiImpl *OrgApiImpl) CreateOrg(ctx context.Context, req *org_api.CreateOrgRequest) (*org_api.CreateOrgResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &org_api.CreateOrgResponse{
			Code:   org_api.CreateOrgResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}

	orgId := uuid.NewString()
	newDepartMentId := uuid.NewString()
	nowTime := time.Now().UnixNano() / 1e6

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		//创建组织
		err = org_dao.OrgInfoDao.Insert(sessCtx, &org_dao.OrgInfoDbItem{
			OrgId: orgId,
			BasicInfo: org_dao.BasicOrgInfoDbItem{
				OrgName: req.BasicInfo.OrgName,
				OrgDesc: req.BasicInfo.OrgDesc,
			},
			CreateTime:            nowTime,
			UpdateTime:            nowTime,
			OwnerUserId:           sessionItem.UserId,
			NewMemberDepartMentId: newDepartMentId,
			DepartMentCount:       1,
			MemberCount:           1,
			Setting: org_dao.SettingDbItem{
				EnableDayReport: req.Setting.EnableDayReport,
				EnbleWeekReport: req.Setting.EnbleWeekReport,
				EnableOkr:       req.Setting.EnableOkr,
				EnableAsset:     req.Setting.EnableAsset,
				EnableEvaluate:  req.Setting.EnableEvaluate,
			},
		})
		if err != nil {
			return nil, err
		}
		//创建默认部门
		err = org_dao.DepartMentDao.Insert(sessCtx, &org_dao.DepartMentInfoDbItem{
			DepartMentId:       newDepartMentId,
			OrgId:              orgId,
			DepartMentName:     "未分配成员",
			ParentDepartMentId: "",
			CreateTime:         nowTime,
			CreateUserId:       sessionItem.UserId,
			UpdateTime:         nowTime,
			SubDepartMentCount: 0,
			SubMemberCount:     0,
			AssetCount:         0,
			EvaluateCount:      0,
		})
		if err != nil {
			return nil, err
		}
		//创建成员
		err = org_dao.MemberDao.Insert(sessCtx, &org_dao.MemberInfoDbItem{
			OrgId:              orgId,
			MemberUserId:       sessionItem.UserId,
			ParentDepartMentId: "",
			CreateTime:         nowTime,
			MemberPermInfo: org_dao.MemberPermInfoDbItem{
				ManageDepartMentPerm:     true,
				ManageAssetCate:          true,
				ManageAllAsset:           true,
				ManageDepartMentAsset:    true,
				ManageSelfAsset:          true,
				ManageEvaluateTarget:     true,
				ViewAllEvaluate:          true,
				ManageDepartMentEvaluate: true,
			},
		})
		if err != nil {
			return nil, err
		}
		return &org_api.CreateOrgResponse{
			Code:  org_api.CreateOrgResponse_CODE_OK,
			OrgId: orgId,
		}, nil
	})

	if err != nil {
		return nil, err
	}
	//发送通知
	go api_common.SendNoticeToUser(context.Background(), sessionItem.UserId, &notices_org.JoinOrgNotice{
		OrgId:        orgId,
		MemberUserId: sessionItem.UserId,
	})
	return ret.(*org_api.CreateOrgResponse), nil
}

func (apiImpl *OrgApiImpl) UpdateOrg(ctx context.Context, req *org_api.UpdateOrgRequest) (*org_api.UpdateOrgResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &org_api.UpdateOrgResponse{
			Code:   org_api.UpdateOrgResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	orgItem, err := org_dao.OrgInfoDao.Get(ctx, req.OrgId)
	if err != nil {
		return &org_api.UpdateOrgResponse{
			Code:   org_api.UpdateOrgResponse_CODE_NO_ORG,
			ErrMsg: "组织不存在",
		}, nil
	}
	if orgItem.OwnerUserId != sessionItem.UserId {
		return &org_api.UpdateOrgResponse{
			Code:   org_api.UpdateOrgResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	nowTime := time.Now().UnixNano() / 1e6

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = org_dao.OrgInfoDao.Update(sessCtx, req.OrgId, &org_dao.BasicOrgInfoDbItem{
			OrgName: req.BasicInfo.OrgName,
			OrgDesc: req.BasicInfo.OrgDesc,
		}, nowTime)
		if err != nil {
			return nil, err
		}
		return &org_api.UpdateOrgResponse{
			Code: org_api.UpdateOrgResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	//发送通知
	go api_common.SendNoticeToOrgScope(context.Background(), req.OrgId, &notices_org.UpdateOrgNotice{
		OrgId: req.OrgId,
	})
	return ret.(*org_api.UpdateOrgResponse), nil
}

func (apiImpl *OrgApiImpl) UpdateOrgSetting(ctx context.Context, req *org_api.UpdateOrgSettingRequest) (*org_api.UpdateOrgSettingResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &org_api.UpdateOrgSettingResponse{
			Code:   org_api.UpdateOrgSettingResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	orgItem, err := org_dao.OrgInfoDao.Get(ctx, req.OrgId)
	if err != nil {
		return &org_api.UpdateOrgSettingResponse{
			Code:   org_api.UpdateOrgSettingResponse_CODE_NO_ORG,
			ErrMsg: "组织不存在",
		}, nil
	}
	if orgItem.OwnerUserId != sessionItem.UserId {
		return &org_api.UpdateOrgSettingResponse{
			Code:   org_api.UpdateOrgSettingResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	nowTime := time.Now().UnixNano() / 1e6

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = org_dao.OrgInfoDao.UpdateSetting(sessCtx, req.OrgId, &org_dao.SettingDbItem{
			EnableDayReport: req.Setting.EnableDayReport,
			EnbleWeekReport: req.Setting.EnbleWeekReport,
			EnableOkr:       req.Setting.EnableOkr,
			EnableAsset:     req.Setting.EnableAsset,
			EnableEvaluate:  req.Setting.EnableEvaluate,
		}, nowTime)
		if err != nil {
			return nil, err
		}
		return &org_api.UpdateOrgSettingResponse{
			Code: org_api.UpdateOrgSettingResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	return ret.(*org_api.UpdateOrgSettingResponse), nil
}

func (apiImpl *OrgApiImpl) ListOrg(ctx context.Context, req *org_api.ListOrgRequest) (*org_api.ListOrgResponse, error) {
	emptyList := []*org_api.OrgInfo{}

	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &org_api.ListOrgResponse{
			Code:    org_api.ListOrgResponse_CODE_WRONG_SESSION,
			ErrMsg:  "会话不存在",
			OrgList: emptyList,
		}, nil
	}
	orgIdList, err := org_dao.MemberDao.DistinctByUser(ctx, sessionItem.UserId)
	if err != nil {
		return nil, err
	}
	orgItemList, err := org_dao.OrgInfoDao.ListById(ctx, orgIdList)
	if err != nil {
		return nil, err
	}
	//补全用户信息
	userIdList := []string{}
	for _, orgItem := range orgItemList {
		userIdList = append(userIdList, orgItem.OwnerUserId)
	}
	userItemList, err := user_dao.UserInfoDao.ListById(ctx, userIdList)
	if err != nil {
		return nil, err
	}
	userItemMap := map[string]*user_dao.UserInfoDbItem{}
	for _, userItem := range userItemList {
		userItemMap[userItem.UserId] = userItem
	}
	//生成结果
	orgInfoList := []*org_api.OrgInfo{}
	for _, orgItem := range orgItemList {
		orgInfo := orgItem.ToOrgInfo()
		ownerUser, ok := userItemMap[orgInfo.OwnerUserId]
		if ok {
			orgInfo.OwnerDisplayName = ownerUser.BasicInfo.DisplayName
			orgInfo.OwnerLogoUri = ownerUser.BasicInfo.LogoUri
		}
		orgInfoList = append(orgInfoList, orgInfo)
	}
	return &org_api.ListOrgResponse{
		Code:    org_api.ListOrgResponse_CODE_OK,
		OrgList: orgInfoList,
	}, nil
}

func (apiImpl *OrgApiImpl) GetOrg(ctx context.Context, req *org_api.GetOrgRequest) (*org_api.GetOrgResponse, error) {
	emptyInfo := &org_api.OrgInfo{
		BasicInfo: &org_api.BasicOrgInfo{},
	}

	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &org_api.GetOrgResponse{
			Code:    org_api.GetOrgResponse_CODE_WRONG_SESSION,
			ErrMsg:  "会话不存在",
			OrgInfo: emptyInfo,
		}, nil
	}
	exist, err := org_dao.MemberDao.Exist(ctx, req.OrgId, sessionItem.UserId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &org_api.GetOrgResponse{
			Code:    org_api.GetOrgResponse_CODE_NO_PERMISSION,
			ErrMsg:  "没有权限",
			OrgInfo: emptyInfo,
		}, nil
	}
	orgItem, err := org_dao.OrgInfoDao.Get(ctx, req.OrgId)
	if err != nil {
		return &org_api.GetOrgResponse{
			Code:    org_api.GetOrgResponse_CODE_NO_ORG,
			ErrMsg:  "组织不存在",
			OrgInfo: emptyInfo,
		}, nil
	}
	//补充用户信息
	userItemList, err := user_dao.UserInfoDao.ListById(ctx, []string{orgItem.OwnerUserId})
	if err != nil {
		return nil, err
	}
	orgInfo := orgItem.ToOrgInfo()
	if len(userItemList) == 1 {
		orgInfo.OwnerDisplayName = userItemList[0].BasicInfo.DisplayName
		orgInfo.OwnerLogoUri = userItemList[0].BasicInfo.LogoUri
	}
	return &org_api.GetOrgResponse{
		Code:    org_api.GetOrgResponse_CODE_OK,
		OrgInfo: orgInfo,
	}, nil
}

func (apiImpl *OrgApiImpl) RemoveOrg(ctx context.Context, req *org_api.RemoveOrgRequest) (*org_api.RemoveOrgResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &org_api.RemoveOrgResponse{
			Code:   org_api.RemoveOrgResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}

	orgItem, err := org_dao.OrgInfoDao.Get(ctx, req.OrgId)
	if err != nil { //组织不存在
		return &org_api.RemoveOrgResponse{
			Code: org_api.RemoveOrgResponse_CODE_OK,
		}, nil
	}
	if orgItem.OwnerUserId != sessionItem.UserId {
		return &org_api.RemoveOrgResponse{
			Code:   org_api.RemoveOrgResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	memberItemList, err := org_dao.MemberDao.ListByOrg(ctx, req.OrgId)
	if err != nil {
		return nil, err
	}

	forumItemList, err := org_dao.ForumDao.List(ctx, req.OrgId)
	if err != nil {
		return nil, err
	}

	nowTime := time.Now().UnixNano() / 1e6

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		//删除成员
		err = org_dao.MemberDao.RemoveByOrg(sessCtx, req.OrgId)
		if err != nil {
			return nil, err
		}
		//删除部门
		err = org_dao.DepartMentDao.RemoveByOrg(sessCtx, req.OrgId)
		if err != nil {
			return nil, err
		}
		//删除邀请
		err = org_dao.InviteDao.RemoveByOrg(sessCtx, req.OrgId)
		if err != nil {
			return nil, err
		}
		//删除OKR
		err = org_dao.OkrDao.RemoveByOrg(sessCtx, req.OrgId)
		if err != nil {
			return nil, err
		}
		//删除日报
		err = org_dao.DayReportDao.RemoveByOrg(sessCtx, req.OrgId)
		if err != nil {
			return nil, err
		}
		//删除周报
		err = org_dao.WeekReportDao.RemoveByOrg(sessCtx, req.OrgId)
		if err != nil {
			return nil, err
		}
		//删除论坛
		err = org_dao.ForumDao.RemoveByOrg(sessCtx, req.OrgId)
		if err != nil {
			return nil, err
		}
		err = org_dao.ForumThreadDao.RemoveByOrg(sessCtx, req.OrgId)
		if err != nil {
			return nil, err
		}
		err = org_dao.ThreadContentDao.RemoveByOrg(sessCtx, req.OrgId)
		if err != nil {
			return nil, err
		}
		//清除文件
		for _, forumItem := range forumItemList {
			bgTaskId := fmt.Sprintf("OrgForumFsClean:%s", forumItem.ForumId)
			exist, err := dao.BgTaskDao.Exist(sessCtx, bgTaskId)
			if err != nil {
				return nil, err
			}
			if !exist {
				err = dao.BgTaskDao.Insert(context.Background(), bgTaskId, nowTime, nowTime+(3600*1000), &tasks.OrgForumFsClean{
					OrgId:        req.OrgId,
					ForumId:      forumItem.ForumId,
					FsId:         forumItem.FsId,
					FsRemoteAddr: apiImpl.fsRemoteAddr,
				})
				if err != nil {
					return nil, err
				}
			}
		}
		//清除资产类别
		err = org_dao.AssetCateDao.RemoveByOrg(sessCtx, req.OrgId)
		if err != nil {
			return nil, err
		}
		//清除资产
		err = org_dao.AssetDao.RemoveByOrg(sessCtx, req.OrgId)
		if err != nil {
			return nil, err
		}
		//清理评估
		err = org_eval_dao.TargetDao.RemoveByOrg(sessCtx, req.OrgId)
		if err != nil {
			return nil, err
		}
		err = org_eval_dao.EvaluateDao.RemoveByOrg(sessCtx, req.OrgId)
		if err != nil {
			return nil, err
		}
		err = org_eval_dao.ResultScoreDao.RemoveByOrg(sessCtx, req.OrgId)
		if err != nil {
			return nil, err
		}
		err = org_eval_dao.VoteScoreDao.RemoveByOrg(sessCtx, req.OrgId)
		if err != nil {
			return nil, err
		}
		//删除组织
		err = org_dao.OrgInfoDao.Remove(sessCtx, req.OrgId)
		if err != nil {
			return nil, err
		}
		return &org_api.RemoveOrgResponse{
			Code: org_api.RemoveOrgResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	//发送通知
	go func() {
		for _, memberItem := range memberItemList {
			api_common.SendNoticeToUser(context.Background(), memberItem.MemberUserId, &notices_org.LeaveOrgNotice{
				OrgId:        req.OrgId,
				MemberUserId: memberItem.MemberUserId,
			})
		}
	}()
	return ret.(*org_api.RemoveOrgResponse), nil
}

func (apiImpl *OrgApiImpl) ChangeOrgOwner(ctx context.Context, req *org_api.ChangeOrgOwnerRequest) (*org_api.ChangeOrgOwnerResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &org_api.ChangeOrgOwnerResponse{
			Code:   org_api.ChangeOrgOwnerResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}

	orgItem, err := org_dao.OrgInfoDao.Get(ctx, req.OrgId)
	if err != nil { //组织不存在
		return &org_api.ChangeOrgOwnerResponse{
			Code:   org_api.ChangeOrgOwnerResponse_CODE_NO_ORG,
			ErrMsg: "组织不存在",
		}, nil
	}
	if orgItem.OwnerUserId != sessionItem.UserId {
		return &org_api.ChangeOrgOwnerResponse{
			Code:   org_api.ChangeOrgOwnerResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	if req.TargetMemberUserId == orgItem.OwnerUserId {
		return &org_api.ChangeOrgOwnerResponse{
			Code: org_api.ChangeOrgOwnerResponse_CODE_OK,
		}, nil
	}
	//检查目标用户是否在项目内
	exist, err := org_dao.MemberDao.Exist(ctx, req.OrgId, req.TargetMemberUserId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &org_api.ChangeOrgOwnerResponse{
			Code:   org_api.ChangeOrgOwnerResponse_CODE_NO_MEMBER,
			ErrMsg: "目标成员不存在",
		}, nil
	}

	nowTime := time.Now().UnixNano() / 1e6

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = org_dao.OrgInfoDao.UpdateOwner(sessCtx, req.OrgId, req.TargetMemberUserId, nowTime)
		if err != nil {
			return nil, err
		}
		return &org_api.ChangeOrgOwnerResponse{
			Code: org_api.ChangeOrgOwnerResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	//发送通知
	go api_common.SendNoticeToOrgScope(context.Background(), req.OrgId, &notices_org.UpdateOrgNotice{
		OrgId: req.OrgId,
	})
	return ret.(*org_api.ChangeOrgOwnerResponse), nil
}
